package com.voodoo.lib_wechatpayface;

import android.content.Context;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.RemoteException;

import com.tencent.wxpayface.IWxPayFaceCallbackAIDL;
import com.tencent.wxpayface.IWxPayfaceCallback;
import com.tencent.wxpayface.WxPayFace;

import java.util.HashMap;
import java.util.Map;

/**
 * Author：voodoo
 * CreateTime：2021/09/26 026 下午 12:53:22
 * Description：微信摄像头人脸识别
 */
public class WeChatFace {

//         Application中初始化            每单都从此进入
//               ↓                           ↓
//    初始化人脸识别SDK(initWxpayface()) => 工具类入口 => 获取rawdata给后台(getWxpayfaceRawdata()) =>
//
//    后台返回authinfo、payscore_out_request_no、payscore_service_id => 调起摄像头(getUserPayScoreStatus()) =>
//
//    刷脸用户支付分状态，将回传的信息给后台

    static WeChatFace weChatFace;
    Context context;
    boolean isInited = false; // 是否初始化成功
    Handler mainHandler;
    private HashMap<String, String> params;

    enum WxpayMethods {
        METHODS_INIT, // 初始化
        METHODS_GET_RAWDATA, // 获取RawData
        METHODS_GET_USER_PAY_SCORE_STATUS, // 刷脸查询用户支付分状态
    }

    public static WeChatFace getInstance() {
        if (weChatFace == null) {
            synchronized (WeChatFace.class) {
                if (weChatFace == null) {
                    weChatFace = new WeChatFace();
                }
            }
        }
        return weChatFace;
    }

    public WeChatFace() {
        mainHandler = new Handler(Looper.getMainLooper());
    }

    /**
     * 该方法是初始化微信支付摄像头
     * 在Application的onCreate中调用
     *
     * @param appContext Application的Context
     */
    public void init(Context appContext) {

        this.context = appContext;

        printLog("initWxpayface初始化微信人脸识别SDK");
        Map<String, String> initParamMap = new HashMap<>();
        initParamMap.put("perform_mode", "LOW_PERFORM"); // 低性能表现，默认关闭美颜等

        // 初始化人脸识别SDK
        WxPayFace.getInstance().initWxpayface(appContext, initParamMap, new IWxPayfaceCallback() {
            @Override
            public void response(Map info) throws RemoteException {
                // 初始化返回的数据 初始化成功，无需其他操作，如果失败，在解析方法中有回调接口
                isInited = parsingReturnCode(WxpayMethods.METHODS_INIT, info);
            }
        });
    }

    /**
     * 开始获取RawData
     */
    public void getRawdata() {
        printLog("是否初始化：" + isInited);
        if (isInited) {
            printLog("获取 rawdata 上传给后台（getWxpayfaceRawdata）");
            // 获取调起摄像头所需的参数 rawdata
            WxPayFace.getInstance().getWxpayfaceRawdata(new IWxPayfaceCallback() {
                @Override
                public void response(Map info) throws RemoteException {
                    if (parsingReturnCode(WxpayMethods.METHODS_GET_RAWDATA, info)) {
                        String rawdata = String.valueOf(info.get("rawdata"));
                        printLog(String.format("获取到的RawData：%s", rawdata));
                        // 将获取到的数据回调出去
                        if (onWeChatSdkListener != null) {
                            onWeChatSdkListener.getRawData(rawdata);
                        }
                    }
                }
            });
        } else {
            if (onWeChatSdkListener != null) {
                onWeChatSdkListener.weChatLog("SDK未成功初始化，无法调用支付");
                mainHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        onWeChatSdkListener.weChatSdkToast("微信SDK未初始化成功");
                    }
                });
            }
        }
    }

    /**
     * 获取后台RawData的返回值之后，调起摄像头
     *
     * @param resultData 返回的数据对象
     */
    public void openCamera(ResultDataBean resultData, String outTradeNo) {

        if (isInited) {
            printLog("设置参数并打开摄像头");
            if (resultData == null) {
                printLog("传入的返回值对象为空，停止之后的操作");
                return;
            }

            params = new HashMap<>();
            params.put("appid", resultData.getAppid()); // 商户号绑定的公众号/小程序appid 必填
            params.put("mch_id", resultData.getMch_id()); // 商户号 必填
            params.put("out_trade_no", outTradeNo); // 商户订单号
            params.put("authinfo", resultData.getAuthinfo()); // 调用凭证 必填

            // TODO 等待后台回传，回传之后修改该地方的数据
            params.put("payscore_out_request_no", resultData.getAuthinfo()); // 商户签约单号 必填
            params.put("payscore_service_id", resultData.getAuthinfo()); // 支付分服务ID 必填
            params.put("ask_unionid", resultData.getAuthinfo()); // 是否请求UnionId 无需必填

            printLog(String.format("拼接调起摄像头的参数，并启动摄像头（getWxpayfaceCode(Map, IWxPayfaceCallback, IWxPayfaceCallback)）。Map：%s", params));

            WxPayFace.getInstance().getUserPayScoreStatus(params, new IWxPayFaceCallbackAIDL() {
                @Override
                public void response(Map map) throws RemoteException {
                    if (parsingReturnCode(WxpayMethods.METHODS_GET_USER_PAY_SCORE_STATUS, map)) {
                        String openId = String.valueOf(map.get("openid")); // 用户标识
                        String subOpenid = String.valueOf(map.get("sub_openid")); // 用户子标识
                        String faceSid = String.valueOf(map.get("face_sid")); // 接口调用凭证
                        printLog(String.format("获取到的用户支付分状态(刷脸结果)：openId：%s  subOpenid：%s  faceSid：%s", openId, subOpenid, faceSid));
                        if (onWeChatSdkListener != null) {
                            onWeChatSdkListener.cameraResult(openId, subOpenid, faceSid);
                        }
                    }
                }

                @Override
                public IBinder asBinder() {
                    return null;
                }
            });
        } else {
            if (onWeChatSdkListener != null) {
                onWeChatSdkListener.weChatLog("SDK未成功初始化，无法调用支付");
                mainHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        onWeChatSdkListener.weChatSdkToast("微信SDK未初始化成功");
                    }
                });
            }
        }
    }

    /**
     * 解析回传的Map值
     *
     * @param wxpayMethods 微信方法接口
     * @param info         详细信息的Map
     * @return 返回验证成功或失败
     */
    private boolean parsingReturnCode(WxpayMethods wxpayMethods, Map<String, String> info) {

        printLog(String.format("WeChatPayFace传入的Map数据：%s", info));

        if (info == null) {
            printLog(wxpayMethods + "传入的数据为空");
            return false;
        }

        String code = info.get("return_code");
        String msg = info.get("return_msg");

        String methodsName = "";
        switch (wxpayMethods) {
            case METHODS_INIT:
                methodsName = "初始化方法";
                break;
            case METHODS_GET_RAWDATA:
                methodsName = "获取RawData";
                break;
            case METHODS_GET_USER_PAY_SCORE_STATUS:
                methodsName = "刷脸查询用户支付分状态";
                break;
        }

        String errorMsg = "";
        if ("SUCCESS".equals(code)) {
            errorMsg = "返回处理数据成功";
        } else if ("ERROR".equals(code)) {
            errorMsg = "接口失败";
        } else if ("PARAM_ERROR".equals(code)) {
            errorMsg = "参数错误";
        } else if ("SYSTEMERROR".equals(code)) {
            errorMsg = "接口返回错误";
        } else if ("USER_CANCEL".equals(code)) {
            errorMsg = "主动取消支付";
        } else {
            errorMsg = "未知异常";
        }

        printLog(String.format("methodsName:%s errorMsg:%s originalMsg:%s", methodsName, errorMsg, msg));

        if (!("SUCCESS".equals(code)) && onWeChatSdkListener != null) {
            String finalErrorMsg = errorMsg;
            mainHandler.post(new Runnable() {
                @Override
                public void run() {
                    onWeChatSdkListener.weChatSdkToast(finalErrorMsg);
                    onWeChatSdkListener.wxPayCancel(finalErrorMsg);
                }
            });
        }

        // 返回 "SUCCESS"表示操作成功，其他的一律为失败
        return "SUCCESS".equals(code);
    }

    /**
     * 释放资源
     * 该方法启用原因主要是：该方法不建议使用，除了需要使用摄像头做另外场景使用的时候才调用 releaseWxpayface。
     * 并且调用此方法之后如再次调用刷脸，需要重新初始化操作，也就是得重启软件或Android系统
     */
    @Deprecated
    public void releaseResources() {
        printLog("释放资源(releaseWxpayface)");
        WxPayFace.getInstance().releaseWxpayface(context);
    }

    // ===================================================================== 微信刷脸支付工具类回调接口

    /**
     * 打印日志
     *
     * @param msg 日志消息
     */
    private void printLog(String msg) {
        System.out.println(msg);
        if (onWeChatSdkListener != null) {
            onWeChatSdkListener.weChatLog(msg);
        }
    }

    OnWeChatSdkListener onWeChatSdkListener; // 微信支付接口

    public void setOnWeChatSdkListener(OnWeChatSdkListener onWeChatSdkListener) {
        this.onWeChatSdkListener = onWeChatSdkListener;
    }

    public interface OnWeChatSdkListener {
        /**
         * Log日志打印
         *
         * @param logMsg
         */
        void weChatLog(String logMsg);

        /**
         * 提示Toast
         *
         * @param toastMsg 展示的信息
         */
        void weChatSdkToast(String toastMsg);

        /**
         * 获取RawData
         *
         * @param rawData 获取到的RawData
         */
        void getRawData(String rawData);

        /**
         * 相机识别人脸返回的数据
         *
         * @param openId    用户标识
         * @param subOpenId 用户子标识
         * @param faceSid   接口调用凭证
         */
        void cameraResult(String openId, String subOpenId, String faceSid);

        /**
         * 支付取消
         */
        void wxPayCancel(String msg);
    }

    // ================================================================= 微信刷脸支付工具类回调接口 END

}
